/****************************************************************************
**
** Copyright (C) 2009-2010 Mist Poryvaev.
** All rights reserved.
** Contact: Mist Poryvaev (mist.poryvaev@gmail.com)
**
** This file is part of the RailWorm project.
**
****************************************************************************/

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "parsetraindata.h"
#include "connectrzd.h"
#include "railwormsplash.h"

QSettings MainWindowSettings("railworm.ini", QSettings::IniFormat);

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {

	RailWormSplash::i()->SetMainWindow(this);
    ui->setupUi(this);

	ui->actionCollapse->setChecked(MainWindowSettings.value("View/Collapsable", true).toBool());
	ui->actionSeatsDetailsVisible->setChecked(MainWindowSettings.value("View/SeatsDetailsVisible", false).toBool());

	m_Parser.SetCollapsable(ui->actionCollapse->isChecked());
	m_Parser.SetSeatsDetailsVisible(ui->actionSeatsDetailsVisible->isChecked());
	m_Parser.SetFirmTrainsList(&m_FirmTrains);

	ui->statusBar->addWidget(m_Progress = new QProgressBar(), 0);
	m_Progress->setVisible(false);
	m_Progress->setMaximumHeight(16);
	m_Progress->setMaximumWidth(200);

	ui->statusBar->addWidget(m_Info = new QLabel());

	ui->statusBar->addWidget(new QWidget(), 1);

	ui->statusBar->addWidget(m_Cancel = new QPushButton(tr("Отмена")), 0);
	m_Cancel->setVisible(false);
	m_Cancel->setMaximumHeight(20);
	connect(m_Cancel, SIGNAL(pressed()), &m_Parser, SLOT(Cancel()));

	m_QueryForm = QueryForm::i();
	connect(m_QueryForm, SIGNAL(Query(QString,QString,QString,QString)), &m_Parser, SLOT(Exec(QString,QString,QString,QString)));
	connect(m_QueryForm, SIGNAL(Query(QString,QString,QString,QString)), this, SLOT(OnQueryStarted()));
	connect(&m_Parser, SIGNAL(MainPageFinished()), &m_Parser, SLOT(Print()));
//	connect(&m_Parser, SIGNAL(SubPagesProcessing()), &m_Parser, SLOT(Print()));
	connect(&m_Parser, SIGNAL(SubPagesFinished()), this, SLOT(OnFinished()));
	connect(&m_Parser, SIGNAL(Error(QString)), this, SLOT(OnError(QString)));
	connect(&m_Parser, SIGNAL(ProgressUpdate(qint64, qint64)), this, SLOT(OnProgressUpdate(qint64, qint64)));

	m_SetupProxy = SetupProxy::i();
	connect(m_SetupProxy, SIGNAL(ProxyChanged(QString,QString)), this, SLOT(OnProxyChanged(QString,QString)));
	if (m_SetupProxy->UseProxy()) {
		rzd::SetProxy(m_SetupProxy->Address(), m_SetupProxy->Port());
	}
	else {
		rzd::SetProxy("", "");
	}

	m_SetupLogon = SetupLogon::i();

	m_OrderTickets = OrderTickets::i();
	connect(&m_Parser, SIGNAL(OrderRequested(TrainDataStruct)), m_OrderTickets, SLOT(Execute(TrainDataStruct)));

	setCentralWidget(m_Parser.Widget());

	connect(this, SIGNAL(NeedRequestFirmTrains()), this, SLOT(RequestFirmTrains()));
	emit NeedRequestFirmTrains();
}

MainWindow::~MainWindow() {
    delete ui;
}

void MainWindow::OnFirmTrainsPageFinished(HtmlResponse * _response, int _id, bool _error) {
	if (_error) {
		delete _response;
		emit NeedRequestFirmTrains();
		qDebug() << "OnFirmTrainsPageFinished error, restart";
		return;
	}

	HtmlElementPars _pars;

/*
	_pars.Class = "Rtable Striped";
	HtmlTableDataList _tables = _response->Tables(_pars);
	qDebug() << "tables count = " << _tables.size();
	int _idx = 0;
	foreach (const HtmlTableData & _table, _tables) {
		qDebug() << "table no." << _idx;
		foreach (const HtmlTableCellData & _cell, _table.Cells) {
			qDebug() << _cell.Text;
		}
		_idx++;
	}
*/

	_pars.Class = "EntityLink";
	HtmlLinkDataList _links = _response->Links(_pars);

	int _count = 0;
	FirmTrainStruct _firmTrain;
	foreach (const HtmlLinkData & _link, _links) {
//		qDebug() << _link.Content;
		if (_count % 3 == 0) {
			QString _number = _link.Content;
			if (_number.contains("/")) {
				_firmTrain.Number1 = _number.split("/").at(0);
				_firmTrain.Number2 = _number.split("/").at(1);
			}
			else {
				_firmTrain.Number1 = "000";
				_firmTrain.Number2 = "000";
			}
		}
		if (_count % 3 == 1) {
			_firmTrain.Name = _link.Content;
			m_FirmTrains << _firmTrain;
		}

		_count++;
	}

	delete _response;

	FirmTrainStruct AdditionalTrain;

	AdditionalTrain.Name = tr("Сапсан");
	AdditionalTrain.Number1 = tr("151А"); AdditionalTrain.Number2 = tr("152А");
	m_FirmTrains << AdditionalTrain;
	AdditionalTrain.Number1 = tr("153А"); AdditionalTrain.Number2 = tr("154А");
	m_FirmTrains << AdditionalTrain;
	AdditionalTrain.Number1 = tr("155А"); AdditionalTrain.Number2 = tr("156А");
	m_FirmTrains << AdditionalTrain;
	AdditionalTrain.Number1 = tr("157А"); AdditionalTrain.Number2 = tr("158А");
	m_FirmTrains << AdditionalTrain;

	AdditionalTrain.Name = tr("Мегаполис");
	AdditionalTrain.Number1 = tr("019У"); AdditionalTrain.Number2 = tr("020У");
	m_FirmTrains << AdditionalTrain;

	AdditionalTrain.Name = tr("Лев Толстой");
	AdditionalTrain.Number1 = tr("031А"); AdditionalTrain.Number2 = tr("032А");
	m_FirmTrains << AdditionalTrain;

	AdditionalTrain.Name = tr("Афанасий Никитин");
	AdditionalTrain.Number1 = tr("037А"); AdditionalTrain.Number2 = tr("038А");
	m_FirmTrains << AdditionalTrain;

	AdditionalTrain.Name = tr("Соловей");
	AdditionalTrain.Number1 = tr("081М"); AdditionalTrain.Number2 = tr("082М");
	m_FirmTrains << AdditionalTrain;

	AdditionalTrain.Name = tr("Гранд-Экспресс");
	AdditionalTrain.Number1 = tr("053Ч"); AdditionalTrain.Number2 = tr("054Ч");
	m_FirmTrains << AdditionalTrain;

	AdditionalTrain.Name = tr("Николаевский Экспресс");
	AdditionalTrain.Number1 = tr("005А"); AdditionalTrain.Number2 = tr("006А");
	m_FirmTrains << AdditionalTrain;

	qDebug() << "OnFirmTrainsPageFinished" << "Firm trains aquired successfully - " << m_FirmTrains.size();

	m_Info->setText(tr("Запрос списка фирменных поездов завершён"));

}


void MainWindow::RequestFirmTrains() {
	m_Info->setText(tr("Выполняется запрос списка фирменных поездов"));
	jinn.Request("http://" + rzd::PassHost() + rzd::Query("FirmTrains"), HtmlGenie::ContentTypeForm(), this, SLOT(OnFirmTrainsPageFinished(HtmlResponse *,int,bool)));
/*
	rzd::Request(
			rzd::PassHost(),
			rzd::Query("FirmTrains"),
			rzd::Text,
			rzd::Local8Bit,
			this,
			SLOT(OnFirmTrainsPageFinished(QString, int,bool)));
*/
}
/*
void MainWindow::OnFirmTrainsPageFinished(QString Response, int Id, bool _Error) {
	if (_Error) {
		emit NeedRequestFirmTrains();
		qDebug() << "OnFirmTrainsPageFinished" << Response;
		return;
	}

	qDebug() << "OnFirmTrainsPageFinished" << "Parsing...";

	foreach(QString Line, Response.split("\n", QString::SkipEmptyParts)) {
		if (Line.contains("EntityLink")) {
			int Count = 0;
			FirmTrainStruct FirmTrain;
			foreach (QString SubLine, Line.split("class=\"EntityLink\">")) {
				if (Count == 1) {
					QString Number = SubLine.split("<").at(0);
					if (Number.contains("/")) {
						FirmTrain.Number1 = Number.split("/").at(0);
						FirmTrain.Number2 = Number.split("/").at(1);
//						qDebug() << FirmTrain.Number1;
//						qDebug() << FirmTrain.Number2;
					}
				}
				if (Count == 2) {
					FirmTrain.Name = SubLine.split("<").at(0);
//					qDebug() << FirmTrain.Name;
					break;
				}
				Count++;
			}
			if (Count == 2) {
				m_FirmTrains << FirmTrain;
			}
		}
	}

	FirmTrainStruct AdditionalTrain;

	AdditionalTrain.Name = tr("Сапсан");
	AdditionalTrain.Number1 = tr("151А"); AdditionalTrain.Number2 = tr("152А");
	m_FirmTrains << AdditionalTrain;
	AdditionalTrain.Number1 = tr("153А"); AdditionalTrain.Number2 = tr("154А");
	m_FirmTrains << AdditionalTrain;
	AdditionalTrain.Number1 = tr("155А"); AdditionalTrain.Number2 = tr("156А");
	m_FirmTrains << AdditionalTrain;
	AdditionalTrain.Number1 = tr("157А"); AdditionalTrain.Number2 = tr("158А");
	m_FirmTrains << AdditionalTrain;

	AdditionalTrain.Name = tr("Мегаполис");
	AdditionalTrain.Number1 = tr("019У"); AdditionalTrain.Number2 = tr("020У");
	m_FirmTrains << AdditionalTrain;

	AdditionalTrain.Name = tr("Лев Толстой");
	AdditionalTrain.Number1 = tr("031А"); AdditionalTrain.Number2 = tr("032А");
	m_FirmTrains << AdditionalTrain;

	AdditionalTrain.Name = tr("Афанасий Никитин");
	AdditionalTrain.Number1 = tr("037А"); AdditionalTrain.Number2 = tr("038А");
	m_FirmTrains << AdditionalTrain;

	AdditionalTrain.Name = tr("Соловей");
	AdditionalTrain.Number1 = tr("081М"); AdditionalTrain.Number2 = tr("082М");
	m_FirmTrains << AdditionalTrain;

	AdditionalTrain.Name = tr("Гранд-Экспресс");
	AdditionalTrain.Number1 = tr("053Ч"); AdditionalTrain.Number2 = tr("054Ч");
	m_FirmTrains << AdditionalTrain;

	AdditionalTrain.Name = tr("Николаевский Экспресс");
	AdditionalTrain.Number1 = tr("005А"); AdditionalTrain.Number2 = tr("006А");
	m_FirmTrains << AdditionalTrain;

	qDebug() << "OnFirmTrainsPageFinished" << "Firm trains aquired successfully - " << m_FirmTrains.size();
}
*/
void MainWindow::on_actionNewQuery_triggered() {
	if (m_QueryForm->isHidden()) {
		m_QueryForm->move(pos().x() + 100, pos().y() + 100);
	}
	m_QueryForm->show();
	m_QueryForm->raise();
}

void MainWindow::OnError(const QString & Text) {
	if (m_QueryForm->isEnabled() == false) {
		m_Parser.Cancel();
//		QMessageBox::information(0, tr("Обработка запроса остановлена"), Text);
		m_Info->setText(tr("Обработка запроса остановлена"));
	}
	m_QueryForm->setEnabled(true);
	m_Progress->setVisible(false);
	m_Cancel->setVisible(false);

	m_Parser.Print();
}

void MainWindow::OnFinished() {
	m_QueryForm->setEnabled(true);
	m_Progress->setVisible(false);
	m_Cancel->setVisible(false);
	UpdateTitle(
			QueryForm::Beautifulize(m_QueryForm->From()),
			QueryForm::Beautifulize(m_QueryForm->To())
			);
	m_Parser.Print();

	m_Info->setText(tr("Обработка запроса завершена"));
}

void MainWindow::OnProgressUpdate(qint64 Done, qint64 Total) {
	m_Progress->setVisible(true);

	m_Progress->setMaximum(Total);
	m_Progress->setValue(Done);

	m_Cancel->setVisible(true);

	m_Info->setText(tr("Обработка запроса выполняется"));
}

void MainWindow::closeEvent(QCloseEvent * ce) {

	MainWindowSettings.setValue("View/Collapsable", ui->actionCollapse->isChecked());
	MainWindowSettings.setValue("View/SeatsDetailsVisible", ui->actionSeatsDetailsVisible->isChecked());

	m_QueryForm->close();
}


void MainWindow::on_actionCollapse_triggered(bool checked) {
	m_Parser.SetCollapsable(checked);
	m_Parser.Print();
}

void MainWindow::on_actionSeatsDetailsVisible_triggered(bool checked) {
	m_Parser.SetSeatsDetailsVisible(checked);
	m_Parser.Print();
}

void MainWindow::UpdateTitle(const QString & From, const QString & To) {
	QString Title = "RailWorm";
	if (From.isEmpty() == false) {
		Title += " - " + From;
	}
	if (To.isEmpty() == false) {
		Title += " - " + To;
	}
	setWindowTitle(Title);
}

void MainWindow::on_actionOptions_triggered() {
	if (m_SetupProxy->isHidden()) {
		m_SetupProxy->move(pos().x() + 100, pos().y() + 100);
	}
	m_SetupProxy->show();
	m_SetupProxy->raise();
}

void MainWindow::OnProxyChanged(QString Address, QString Port) {
//	rzd::SetProxy(Address, Port);

	if ((Address.isEmpty() == false) && (Port.toInt() > 0)) {
		HtmlGenie::NetMan().setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, Address, Port.toInt()));
	}
	else {
		HtmlGenie::NetMan().setProxy(QNetworkProxy::NoProxy);
	}
}

void MainWindow::OnQueryStarted() {
	m_Cancel->setVisible(true);
}




void MainWindow::on_actionAbout_triggered() {
	QVBoxLayout * l = new QVBoxLayout();
	l->setMargin(2);
	l->setSpacing(2);
	QTextBrowser * te = new QTextBrowser;
	te->setReadOnly(true);
	te->setOpenExternalLinks(true);
	te->setHtml(
			tr("<center><b>RailWorm версия 0.2.0</b></center><br/>") +
			tr("<center>© 2009-2010 <a href=\"mailto:mist.poryvaev@gmail.com\">Мист Порываев</a></center>") +
			tr("<center><a href=\"http://railworm.googlecode.com\">Сайт RailWorm</a></center>") +
			tr("<br/><center>Вы можете поддержать проект, перечислив любую сумму через WebMoney на кошельки </center>") +
			tr("<center><b>Z352710224225</b> или <b>R146093034989</b>.</center>")
			);
	te->setMaximumSize(300, 150);
	l->addWidget(te);
	QHBoxLayout * l2 = new QHBoxLayout();
	l2->setMargin(0);
	l2->setSpacing(0);
	l2->addItem(new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Fixed));
	QPushButton * ok = new QPushButton(tr("OK"));
	l2->addWidget(ok);
	l->addLayout(l2);
	QDialog dlg(this);
	dlg.setWindowTitle(tr("О программе RailWorm"));
	l->setSizeConstraint(QLayout::SetFixedSize);
	dlg.setLayout(l);
	connect(ok, SIGNAL(clicked()), &dlg, SLOT(accept()));
	dlg.exec();
}

void MainWindow::on_actionLogon_triggered() {
	if (m_SetupLogon->isHidden()) {
		m_SetupLogon->move(pos().x() + 100, pos().y() + 100);
	}
	m_SetupLogon->show();
	m_SetupLogon->raise();
}

void MainWindow::on_actionPrint_triggered() {
	QPrinter _printer(QPrinter::HighResolution);;
	_printer.setPageSize(QPrinter::A4);
	_printer.setOrientation(QPrinter::Portrait);

	QPrintDialog _printDialog(& _printer, this);
	_printDialog.setPrintRange(QAbstractPrintDialog::AllPages);
	if (_printDialog.exec() == QPrintDialog::Rejected) {
		return;
	}

	// idea from http://www.qtcentre.org/threads/3796-QTableView-printing#9

	QTableWidget * _table = m_Parser.Table();
	int _w = 0, _h = 0;
	for (int _idx = 0; _idx < _table->rowCount(); _idx++) {
		_h += _table->rowHeight(_idx);
	}
	for (int _idx = 0; _idx < _table->columnCount(); _idx++) {
		_w += _table->columnWidth(_idx);
	}


	QPainter _painter(&_printer);

	// calculate proper scale factors
	double _scale = qMin<double>(_printer.pageRect().width() / _w, _printer.pageRect().height() / _h);
	_painter.scale(_scale, _scale);


	// paint cells
	QStyleOptionViewItemV4 _options;
	_options.features = QStyleOptionViewItemV4::WrapText;
	_options.displayAlignment = Qt::AlignCenter;
	for (int r = 0; r < _table->rowCount(); r++) {
		for (int c = 0; c < _table->columnCount(); c++) {
			QModelIndex idx = _table->model()->index(r, c);
			_options.rect = _table->visualRect(idx);
			_table->itemDelegate()->paint(&_painter, _options, idx);
		}
	}



/*
	// redirect table's painting on a pixmap
	QPixmap _pixmap(_w, _h);
	QPainter::setRedirected(_table->viewport(), &_pixmap);
	QPaintEvent _event(QRect(0, 0, _w, _h));
	qApp->sendEvent(_table->viewport(), &_event);
	QPainter::restoreRedirected(_table->viewport());

	// print scaled pixmap
	QPainter _painter(&_printer);
	_painter.drawPixmap(_printer.pageRect(), _pixmap, _pixmap.rect());
*/
}
